from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.urls import reverse
from django.views import View

from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView

# 导入加密库
import hashlib

# 导入图片库
# 绘画库
from PIL import ImageDraw

# 字体库
from PIL import ImageFont

# 图片库
from PIL import Image

# 随机库
import random

# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango import settings
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

# 导入序列化类
from myapp.myser import UserSer

# 导入中间件
from django.utils.deprecation import MiddlewareMixin

# 定义ip
host = 'localhost'

# 使用docker
# host = '192.168.99.100'
# port = '6380'

# 建立服务连接
r = redis.Redis(host=host)


# 使用docker，建立连接
# r = redis.Redis(host=host, port=port)


# 构造钉钉登录url
def ding_url(request):
    # appid
    appid = 'dingoahmelrgy51wltnjzs'
    # 回调域名
    redirect_uri = 'http://localhost:8000/dingding_back'

    return redirect(
        'https://oapi.dingtalk.com/connect/qrconnect?appid=dingoahmelrgy51wltnjzs&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=http://localhost:8000/dingding_back')


import time
import hmac
import base64
from hashlib import sha256
import urllib
import json


# 构造钉钉回调方法
def ding_back(request):
    # 获取code
    code = request.GET.get("code")
    print(code)

    t = time.time()
    # 时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret = 'fp3nkGoIhS2Mi9EdVql_nKXg6Y0-HSGp-2F_p7IAv_Quc56yhhrinpqbcQRg3RqF'
    # 构造签名
    signature = base64.b64encode(
        hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
        signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoahmelrgy51wltnjzs",
                        data=json.dumps(payload), headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict['user_info']['nick'])
    # return HttpResponse(res.text)

    # 判断是否为第一次登录
    user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

    ding_id = ''
    user_id = ''

    if user:
        # 代表曾经用过钉钉登录
        ding_id = user.username
        user_id = user.id

    else:
        # 代表首次登录，入库
        user = User(username=str(res_dict['user_info']['nick']), password='')
        # 保存入库
        user.save()
        ding_id = str(res_dict['user_info']['nick'])
        # 查询用户id
        user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()
        user_id = user.id
    # 进行跳转
    return redirect('http://localhost:8080?ding_id=' + str(ding_id) + '&uid=' + str(user_id))


# 定义微博回调视图
def wb_back(request):
    # 获取回调的code
    code = request.GET.get('code')

    # 定义认证地址
    access_token_url = 'https://api.weibo.com/oauth2/access_token'

    # 发起请求，交互sina的id
    re_dict = requests.post(
        access_token_url,
        data={
            'client_id': '2636039333',  # 应用id
            'client_secret': '4e2fbdb39432c31dc5c2f90be3afa5ce',  # 密钥
            'grant_type': 'authorization_code',  # 授权方式
            'code': code,  # code
            'redirect_uri': 'http://127.0.0.1:8000/md_admin/weibo'  # 回调网址
        }
    )
    # 获取返回值
    re_dict = re_dict.text

    # 强转
    re_dict = eval(re_dict)
    print(re_dict)

    # 判断是否为第一次登录
    user = User.objects.filter(username=str(re_dict['uid'])).first()

    sina_id = ''
    user_id = ''

    if user:
        # 代表曾经用过新浪登录
        sina_id = user.username
        user_id = user.id

    else:
        # 代表首次登录，入库
        user = User(username=str(re_dict['uid']), password='')
        # 保存入库
        user.save()
        sina_id = str(re_dict['uid'])
        # 查询用户id
        user = User.objects.filter(username=str(re_dict['uid'])).first()
        user_id = user.id
    # 进行跳转
    return redirect('http://localhost:8080?sina_id=' + str(sina_id) + '&uid=' + str(user_id))


# 定义验证码类
class MyCode(View):
    # 定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)

    def get(self, request):
        # 定义画布
        img__size = (120, 50)
        # 定义画笔
        image = Image.new('RGB', img__size, 'white')
        # 定义绘图对象
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机串
        source = '0123456789abcdefghijklmnopqrstuvwxyz'
        # 定义好容器，方便存入redis
        code_str = ''
        for i in range(4):
            # 获取随机颜色
            text_color = self.get_random_color()
            # 获取随机字符串
            tmp_num = random.randrange(len(source))
            # 通过下标获取字符集
            random_str = source[tmp_num]
            # 添加到容器
            code_str += random_str
            # 绘制图像(大小，字符集，字体颜色)
            draw.text((10 + 30 * i, 20), random_str, text_color)
        # 定义缓冲区
        buf = io.BytesIO()
        # 保存到缓冲区
        image.save(buf, 'png')
        # 保存到redis
        r.set('code', code_str)
        # 存储到session
        request.session['code'] = code_str

        return HttpResponse(buf.getvalue(), 'image/png')


# # 导入验证码
# from static.captcha.captcha import captcha
#
#
# # 验证码接口
# class ImageCode(View):
#     def get(self, request):
#         name, text, image = captcha.generate_captcha()
#         # 验证码文字
#         request.session['imagecode'] = text
#         response = HttpResponse(image)
#         #
#         response['Content-Type'] = 'image/jpg'
#         return response


# 上传头像/视频
class UploadFile(View):
    def post(self, request):
        # 接收文件
        file = request.FILES.get('file')
        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '', file.name), 'wb')
        # 写文件，遍历写入
        for chunk in file.chunks():
            f.write(chunk)
        # 关闭文件流
        f.close()
        # 返回图片文件名
        return HttpResponse(json.dumps({'filename': file.name}, ensure_ascii=False), content_type='application/json')


# # 上传视频
# class UploadMv(View):
#     def post(self, request):
#         # 接收文件
#         mv = request.FILES.get('file')
#         # 建立文件流对象
#         f = open(os.path.join(UPLOAD_ROOT, '', mv.name), 'wb')
#         # 写文件
#         for chunk in mv.chunks():
#             f.write(chunk)
#         # 关闭文件流
#         f.close()
#         # 返回视频文件名
#         return HttpResponse(json.dumps({'filename': mv.name}, ensure_ascii=False), content_type='applicationjson')


# 用户修改接口
class UserUpdate(APIView):

    def get(self, request):
        # 接收参数
        uid = request.GET.get('uid', '')
        print(uid)

        # 图片（原始文件名）
        file = request.GET.get('file', '')

        # 查询数据
        user = User.objects.get(id=int(uid))

        # 保存数据
        user.file = file
        user.save()

        # 返回
        res = {}
        res['code'] = 200
        res['message'] = '用户更新成功'
        return Response(res)

    def post(self, request):
        # 接收参数
        uid = request.GET.get('uid', '')
        print(uid)

        # 图片（原始文件名）
        file = request.GET.get('file', '')

        # 查询数据
        user = User.objects.get(id=int(uid))

        # 保存数据
        user.file = file
        user.save()

        # 返回
        res = {}
        res['code'] = 200
        res['message'] = '用户更新成功'
        return Response(res)


# 获取用户信息接口
class UserGetOne(APIView):

    def get(self, request):
        # 接收参数
        uid = request.GET.get('uid', '')
        print(uid)
        # 查询数据
        user = User.objects.get(id=int(uid))

        # 序列化
        user_ser = UserSer(user)

        # 返回数据
        return Response(user_ser.data)


# 登录接口
class Login(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username', '')
        password = request.GET.get('password', '')

        # 查询数据
        user = User.objects.filter(username=username, password=make_password(password)).first()
        if user:
            res = {}
            res['code'] = 200
            res['message'] = '登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '您的用户名或密码错误'
            return Response(res)


# md5加密方法
def make_password(mypass):
    # 建立md5对象
    md5 = hashlib.md5()
    # 转码
    mypass = str(mypass).encode(encoding='utf8')
    # 加密操作
    md5.update(mypass)
    # 生成密文
    password = md5.hexdigest()
    # 返回密文
    return password


# 注册接口
class Register(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username', '')
        password = request.GET.get('password', '')
        code = request.GET.get('code', '')
        print(code, '这个是前端传来的')

        # imagecode = request.GET.get('imagecode', '')

        # 获取redis中的验证码
        mycode = r.get('code')
        # 转码
        mycode = mycode.decode('utf-8')
        print(mycode, '这个是redis内的')

        # 获取session中的验证码
        mycode_session = request.session.get('code', None)

        print(mycode_session)

        # 进行对比操作
        if code != mycode:
            res = {}
            res['code'] = 405
            res['message'] = '验证码输入错误'
            return Response(res)

        # if not imagecode:
        #     res = {}
        #     res['code'] = 405
        #     res['message'] = '验证码错误'
        #     return Response(res)
        #
        # if imagecode.lower() == request.session['imagecode'].lower():
        #     res = {}
        #     res['code'] = 200
        #     res['message'] = '验证码正确'
        #     return Response(res)

        # 排重操作
        user = User.objects.filter(username=username).first()
        if user:
            res = {}
            res['code'] = 405
            res['message'] = '用户已存在'
            return Response(res)

        # 进行入库操作
        # 实例化对象
        user = User(username=username, password=make_password(password))
        # 保存
        user.save()

        # 返回结果
        res = {}
        res['code'] = 200
        res['message'] = '注册成功'

        return Response(res)
